文章同步發表至 Medium
既然有了 DotSpatial 可以處理 Shapefile,為甚麼我還要學習另外兩種工具呢?
使用 DotSpatial 沒多久之後我就遇到了一個神奇的問題:資料庫的內容一樣,讀取的數量也都一樣,但每個環境:local、STG、Prod 所生產出來的 Shapefile 中,Feature 數量都不一樣。 ?
由於一直研究不出一個原因,所以我選擇改用別的套件,也就是我們接下來要介紹的 GDAL。
.NET Framework 和 .NET Core 所安裝的 Nuget 套件不太相同:
安裝完下列的套件之後,會自動長出兩個 Configuration 的檔案,只需要保留副檔名是 .cs 的檔案就好,並且加上專案的命名空間就可以開始使用了。
套件名稱 | 版本 |
---|---|
GDAL | 3.5.1 |
GDAL.Native | 3.5.1 |
如果使用 .NET 安裝上面兩個套件的話,應該在運行時會出現錯誤:
Unable to load DLL 'gdal_wrap' or one of its dependencies
因此 .NET 需要改成安裝 Gdal.Core
才有辦法正常運行。
套件名稱 | 版本 |
---|---|
Gdal.Core | 1.0.0 |
GDAL 對於 Shapefile 的讀取方式比較完整。之前有提到所有的內容都會寫在 Feature 上,而 Feature 的集合就是一層 Layer,一個 Shapefile 可以擁有多個 Layer。
這裡所讀取的檔案是我另外用 QGIS 建立的,有需要的話可以從 GitHub 上取得。
// 註冊 GDAL
Gdal.AllRegister();
Ogr.RegisterAll();
// 開啟 SHP 檔案(0 - 讀取、1 - 讀寫)
var source = Ogr.Open("test.shp", (int)EnumShapefileOpen.ReadOnly);
var layerCount = source.GetLayerCount();
for (var i = 0; i < layerCount; i++)
{
// 讀取圖層 Layer 資訊
var layer = source.GetLayerByIndex(i);
var fieldCount = layer.GetLayerDefn().GetFieldCount();
for (var j = 0; j < fieldCount; j++)
{
var field = layer.GetLayerDefn().GetFieldDefn(j);
var fieldName = field.GetName();
Console.WriteLine($"欄位{j + 1}. {fieldName}");
}
// 讀取要素 Feature
Feature feature;
while ((feature = layer.GetNextFeature()) != null)
{
var id = feature.GetFieldAsInteger(0);
Console.WriteLine($"內容1. Id: {id}");
var name = feature.GetFieldAsString(1);
Console.WriteLine($"內容2. 土地名稱: {name}");
var area = feature.GetFieldAsInteger64(2);
Console.WriteLine($"內容3. 土地面積: {area}");
// 轉換成 WKT 的值
var geometry = feature.GetGeometryRef();
geometry.ExportToWkt(out var wkt);
Console.WriteLine($"- WKT: {wkt}");
}
}
public enum EnumShapefileOpen
{
ReadOnly
}
執行後的結果如下:
而原本的檔案內容是長這樣:
可以觀察到中文的內容會變成亂碼,但明明欄位的名稱原本也是中文,卻可以好好地顯示。這件事情不是單純改變檔案編碼可以解決的事情,因為需要花一點篇幅解釋,所以會把這個問題的原因和解法放在下一篇。